package com.tianlang.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.type.Type;
import org.springframework.transaction.annotation.Transactional;

import com.tianlang.util.CompareColumn;
import com.tianlang.util.SortColumn;
@Transactional(readOnly = false)
@SuppressWarnings("rawtypes")
public interface IBaseDao<T> {
	
	//Hibernate中的对象有3种状态：Transient（瞬时），Persistent（持久）和Detached（托管）。
	/**
	 * 持久化对象
	 * @param entity
	 */
	public void save(final Object entity);
	
	/**
	 * 删除对象
	 * @param entity
	 */
	public void delete(final Object entity);
	
	/**
	 * 删除单挑数据
	 * @param clazz
	 * @param id
	 */
	public void delete(Class clazz, Serializable id);
	
	/****
	 * 删除数据
	 */
	public void delete(String hql);
	
	/****
	 * 删除数据
	 * @param query
	 *            删除需要执行的HQL
	 * @param objects
	 *            执行HQL所需参数
	 * @param types
	 *            执行参数的参数类型
	 */
	public void delete(final String query, final Object[] objects,
			final Type[] types);

	/**
	 * 修改对象
	 * @param entity
	 */
	public void update(final Object entity);

	/***
	 * 托管修改
	 * @param entity
	 */
	public void saveMerge(Object entity);

	/****
	 * 保存或修改
	 * @param entiry
	 */
	public void saveOrUpdate(final Object entiry);
	
	/**
	 * 保存或修改对象(多个)
	 * @param c
	 */
	public void saveOrUpdateAll(Collection c);
	
	/**
	 * 获得对象
	 * @param entity
	 * @param id
	 */
	public Object load(final Class entity, final Serializable id);

	/**
	 * 加载全部对象
	 * 谨慎使用，将会加载整个表的数据
	 * @param entity
	 * @return 整个表的数据
	 */
	public List findAll(final Class entity);
	
	/**
	 * 获得指定类型的所有数据 谨慎使用，将会加载整个表的数据
	 * @param clazz
	 *            数据类型
	 * @return 结果集
	 */
	public List getObjects(Class clazz);

	/*****
	 * 查询预先定义好的HQL<br>
	 * eq: <br>
	 * hbm文件预先定义：<br>
	 * &lt;query name="byname"&gt;<br>
	 * &lt;![from User where u.name = 'abc']]&gt;<br>
	 * &lt;/query&gt;<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param namedQuery
	 *            预先定义的HQL名称
	 * @return 结果集
	 */

	public List findByNamedQuery(final String namedQuery);

	/*****
	 * 查询预先定义好的HQL<br>
	 * eq: <br>
	 * hbm文件预先定义：<br>
	 * &lt;query name="byname"&gt;<br>
	 * &lt;![from User where u.name = ?]]&gt;<br>
	 * &lt;/query&gt;<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param query
	 * @param parameter
	 *            查询参数
	 * @return 查询结果集
	 */
	public List findByNamedQuery(final String query, final Object parameter);

	/*****
	 * 查询预先定义好的HQL<br>
	 * eq: <br>
	 * hbm文件预先定义：<br>
	 * &lt;query name="byname"&gt;<br>
	 * &lt;![from User where u.name = ? and limit ?,?]]&gt;<br>
	 * &lt;/query&gt;<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param query
	 *            查询语句名
	 * @param parameters
	 *            查询参数
	 * @return 查询结果集
	 */
	public List findByNamedQuery(final String query, final Object[] parameters);

	/****
	 * 执行HQL语句<br>
	 * @param query
	 *            HQL语句
	 * @return 查询结果集
	 */
	public List find(final String query);

	/**
	 * 获得单条数据
	 * @param clazz
	 * @param id
	 * @return 结果集，未找到结果将获返回空
	 */
	public Object getObject(Class clazz, Serializable id);
	
	/****
	 * 执行HQL语句<br>
	 * @param query
	 *            HQL语句
	 * @param parameter
	 * @return 查询结果集
	 */
	public List find(final String query, final Object parameter);
	
	/****
	 * 执行HQL语句<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param query
	 *            HQL语句
	 * @param objects
	 *            查询参数
	 * @param types
	 *            查询参数类型
	 * @return 查询结果集
	 */
	public List find(final String query, final Object[] objects,
			final Type[] types);
	
	/******
	 * 执行HQL语句
	 * 注意限制查询结果集数量
	 * @param query  HQL语句
	 * @param objects  查询参数
	 * @return
	 */
	public List find(final String query, final Object[] objects);

	/******
	 * 获得配置信息<br>
	 * 执行这样一个查询 select scd.paramvalue from Sysparam scd where scd.paramkey =:key
	 * @param key
	 *            配置名
	 * @return 值
	 */
	public String getConfigurationValue(String key);
	
	/**
	 * 统计查询<br>
	 * 查询符合条件的数据条数 ，类似select count(*) where ...<br>
	 * eg: searchMap.put("username","xiaoming");<br>
	 * getTotalSize(User.class,searchMap);<br>
	 * 
	 * @param clz
	 *            查询类型
	 * @param searchMap
	 *            查询条件
	 * @return 符合条件的数据条数
	 */

	public Integer getTotalSize(Class clz, Map<String, Object> searchMap,
			String groupColumn);
	
	/***
	 * 根据记录创建者查询<br>
	 * 指定数据创建者ID，获得创建者创建的所有数据。 谨慎使用，未限制结果集大小，你可能获得整个表的数据
	 * 
	 * @param clz
	 *            查询类型
	 * @param creatorId
	 *            创建者ID
	 * @param updateTime
	 *            修改时间
	 * @return 查询结果集
	 */

	public List getObjectByCreator(Class clz, Long creatorId, String updateTime);

	/***
	 * 根据记录创建者查询<br>
	 * 指定数据创建者ID，获得创建者创建的所有数据。 谨慎使用，未限制结果集大小，你可能获得整个表的数据
	 * 
	 * @param clz
	 *            查询类型
	 * @param creatorId
	 *            创建者ID
	 * @return 查询结果集
	 */
	public List getObjectByCreator(Class clz, Long creatorId);
	
	/*****
	 * 查询 谨慎使用，注意限制结果集大小<br>
	 * "本表查询条件"指在HQL中类似"username"这样不涉及别其他关联表的查询条件，
	 * "连接查询条件"指在HQL中类似"address.city"这样中间带点的查询条件，否则方法将不能正常获得查询结果，
	 * 并且对于“连接查询条件”不允许类似“user.address.city”两次连接的写法<br>
	 * 只会返回记过集的第一个对象，如果结果集不为空的话 eg: searchMap.put("username","abc");<br>
	 * getPaginationObjects(User.class,searchMap);<br>
	 * eg1:对于模糊查询你可以这样，<br>
	 * searchMap.put("username",Constants.LIKE+"abc");<br>
	 * getPaginationObjects(User.class,searchMap);<br>
	 * 
	 * @param clz
	 *            查询类型
	 * @param searchMap
	 *            本表查询条件
	 * @return 查询结果集第一个对象
	 */
	public Object getObjectByParams(Class clz, Map<String, Object> searchMap);
	
	/**
	 * 分页查询
	 * @param where
	 * @param objects
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	public <E> List<E> getListByWhere(String where, Object[] objects,
			Integer pageIndex, Integer pageSize);

	/**
	 * 通过实体类例子分页查询
	 * @param obj
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	public List<Object> findByExample(Object obj, Integer pageIndex,
			Integer pageSize);

	/**
	 * 总条数查询
	 * @param where
	 * @param values
	 * @return
	 */
	public Object getCount(String where, Object[] values);
	public Integer getTotalRecordCount(String where, Object[] objects);
	/**
	 * 总条数查询
	 * @param where
	 * @param values
	 * @return
	 */
	public Integer getTotalRecordCount(final String where, final boolean cache);
	/**
	 * 分页查询【start=(pageIndex - 1) * pageSize】
	 * @param where
	 * @param objects
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	public <E> List<E> getObjectsWhere(final String where, final Object[] objects,
			final Integer start, final Integer size);
	///////////////////////////////////表的级联//////////////////////////////////////
	/*****
     *  统计查询<br>
     *  "本表查询条件"指在HQL中类似"username"这样不涉及别其他关联表的查询条件，<br>
     *  "连接查询条件"指在HQL中类似"address.city"这样中间带点的查询条件，否则方法将不能正常获得查询结果，<br>
     *  并且对于“连接查询条件”不允许类似“user.address.city”两次连接的写法<br>
     *  CompareColumn 对象包含key,value,dir 分别为字段名，字段值，计算连接符，"计算连接符"是指字段名与字段值中间的计算符，例如："from user where username = 'abc'"中"="为计算连接符，
     *  计算连接符可以为"eq","ge","gt","le","lt"中的一个，<br>
     *  eg: searchMap.put("username","abc");<br>
     *  searchClassMap.put("address.ctiy","beijin");<br>
     *  compareColumns.put(new CompareColumn("age",CompareColumn.lt,18));<br>
     *  getPaginationObjects(User.class,searchMap,searchClassMap,compareColumns);<br>
     *  eg1:对于模糊查询你可以这样，
     *  searchMap.put("username",Constants.LIKE+"abc");<br>
     *  searchClassMap.put("address.ctiy","beijin");<br>
     *  compareColumns.put(new CompareColumn("age",CompareColumn.lt,18));<br>
     *  getPaginationObjects(User.class,searchMap,searchClassMap,compareColumns);<br>
     *  
     * @param clz 查询类型
     * @param searchMap 本表查询条件
     * @param searchClassMap 连接查询条件
     * @param compareColumns 计算连接符查询条件
     * @return 查询结果集数量
     */
    public Integer getPaginationObjects(Class clz, Map<String, Object> searchMap, Map<String, Object> searchClassMap, List<CompareColumn> compareColumns);
    /*****
     *  分页查询
     *  "本表查询条件"指在HQL中类似"username"这样不涉及别其他关联表的查询条件，
     *  "连接查询条件"指在HQL中类似"address.city"这样中间带点的查询条件，否则方法将不能正常获得查询结果，
     *  并且对于“连接查询条件”不允许类似“user.address.city”两次连接的写法<br>
     *  CompareColumn 对象包含key,value,dir 分别为字段名，字段值，计算连接符，"计算连接符"是指字段名与字段值中间的计算符，例如："from user where username = 'abc'"中"="为计算连接符，
     *  计算连接符可以为"eq","ge","gt","le","lt"中的一个，
     *  eg: searchMap.put("username","abc");<br>
     *  searchClassMap.put("address.ctiy","beijin");<br>
     *  compareColumns.put(new CompareColumn("age",CompareColumn.lt,18));<br>
     *  scs.add(new SortColumn("id","desc"));<br>
     *  getPaginationObjects(User.class,searchMap,searchClassMap,compareColumns,scs);<br>
     *  eg1:对于模糊查询你可以这样，<br>
     *  searchMap.put("username",Constants.LIKE+"abc");<br>
     *  searchClassMap.put("address.ctiy","beijin");<br>
     *  compareColumns.put(new CompareColumn("age",CompareColumn.lt,18));<br>
     *  scs.add(new SortColumn("id","desc"));<br>
     *  getPaginationObjects(User.class,searchMap,searchClassMap,compareColumns,scs);<br>
     * @param clz 查询类型
     * @param pageIndex 页码
     * @param pageSize 每页条数
     * @param searchMap 本表查询条件
     * @param searchClassMap 连接查询条件
     * @param compareColumns 计算连接符查询条件
     * @param scs 排序
     * @return 查询结果集
     */
    public List<Object> getPaginationObjects(Class clz, final int pageIndex, final int pageSize,Map<String, Object> searchMap, Map<String, Object> searchClassMap,List<CompareColumn> compareColumns, List<SortColumn> scs);
    /*****
     *  分页查询
     *  "本表查询条件"指在HQL中类似"username"这样不涉及别其他关联表的查询条件，
     *  "连接查询条件"指在HQL中类似"address.city"这样中间带点的查询条件，否则方法将不能正常获得查询结果，
     *  并且对于“连接查询条件”不允许类似“user.address.city”两次连接的写法<br>
     *  eg: searchMap.put("username","abc");<br>
     *  searchClassMap.put("address.ctiy","beijin");<br>
     *  scs.add(new SortColumn("id","desc"));<br>
     *  getPaginationObjects(User.class,searchMap,searchClassMap,scs);<br>
     *  eg1:对于模糊查询你可以这样，<br>
     *  searchMap.put("username",Constants.LIKE+"abc%");<br>
     *  searchClassMap.put("address.ctiy","beijin");<br>
     *  scs.add(new SortColumn("id","desc"));<br>
     *  getPaginationObjects(User.class,searchMap,searchClassMap,scs);<br>
     * @param clz 查询类型
     * @param pageIndex 页码
     * @param pageSize 每页条数
     * @param searchMap 本表查询条件
     * @param searchClassMap 连接查询条件
     * @param scs 排序
     * @return 查询结果集
     */
	  public List<Object> getPaginationObjects(Class clz, int pageIndex,int pageSize, Map<String, Object> searchMap, Map<String, Object> searchClassMap, List<SortColumn> scs);
	  public List<Object> getPaginationObjects(Class clz, int pageIndex,int pageSize, Map<String, Object> searchMap, Map<String, Object> searchClassMap, List<SortColumn> scs,String groupColumn);
	  /*****
       *  统计查询
       *  
       *  "本表查询条件"指在HQL中类似"username"这样不涉及别其他关联表的查询条件，
       *  "连接查询条件"指在HQL中类似"address.city"这样中间带点的查询条件，否则方法将不能正常获得查询结果，
       *  并且对于“连接查询条件”不允许类似“user.address.city”两次连接的写法<br>
       *  eg: searchMap.put("username","abc");<br>
       *  searchClassMap.put("address.ctiy","beijin");<br>
       *  getPaginationObjects(User.class,searchMap,searchClassMap);<br>
       *  eg1:对于模糊查询你可以这样，<br>
       *  searchMap.put("username",Constants.LIKE+"abc");<br>
       *  searchClassMap.put("address.ctiy","beijin");<br>
       *  getPaginationObjects(User.class,searchMap,searchClassMap);<br>
       * @param clz 查询类型
       * @param searchMap 本表查询条件
       * @param searchClassMap 连接查询条件
       * @return 查询结果集数量
       */
	  public Integer getPaginationObjects(Class clz, Map<String, Object> searchMap, Map<String, Object> searchClassMap);
	  public List getObjectsByParams(Class clz, Map<String, Object> searchMap,Map<String, Object> searchClassMap, List<SortColumn> scs);
	
	///////////////////////////////////sql////////////////////////////////////////
	/**
	 * 分页查询
	 * @param sql
	 * @param object
	 * @param pageIndexs
	 * @param pageSizes
	 * @param pojoClass
	 * @return
	 */
	public List<Object> querySQL(String sql,Object[] object,Integer pageIndexs,Integer pageSizes,Class<?> pojoClass);
	/**
	 * 分页查询
	 * @param sql
	 * @param object
	 * @param pageIndexs
	 * @param pageSizes
	 * @param pojoClass
	 * @return Dto
	 */
	public List<Object> querySQLDto(String sql,Object[] object,Integer pageIndexs,Integer pageSizes,Class<?> pojoClass);
	/**
	 * 查询条数
	 * @param sql
	 * @return 记录条数
	 */
	public Integer querySQLCount(String sql);
	
	/**
	 * 查询
	 * @param sql
	 * @param object
	 * @param pojoClass
	 * @return
	 */
	public List<Object> querySQL(String sql,Object[] object,Class<?> pojoClass);
	/**
	 * 更新
	 * @param Sql
	 */
	public void executeSQL(final String Sql);
}
